<?php
class eTplParser extends EObject{
	/**
	* 模板文件内容
	*
	* @access private
	*/
	var $_template;
	/*
	* 模板存放目录
	* 
	* @access private
	*/
	var $_tplDir;

	/*
	 * 模板编译目录
	 * 
	 */
	var $_cplDir;

	/**
	 * 模板目录访问url
	 */
	var $_urlThemeRoot;
	var $_combinChild=true;
	/**
	* eTplParser Constructor
	*
	* @param string $template_filename HTML Template Filename
	*/
	function __construct($options=array()) {
		$this->_urlThemeRoot = getThemesDir();
		//debug($this->_urlThemeRoot);
		if($options)$this->setFrom($options);
	}
	function _init($tpl) {
		if (file_exists($tpl)) {
			$hd = fopen($tpl, "r");
			$size = filesize($tpl);
			if ($size) {
				$this->_template = fread($hd, $size);
				$this->_tplDir = dirname($tpl) . DIRECTORY_SEPARATOR;
			} else {
				trigger_error('Parser Error: File size is zero byte: ' . "'$tpl'", E_USER_ERROR);
			}
		} else {
			trigger_error('Parser Error: Template File not found:' . "'$tpl'", E_USER_ERROR);
		}
	}
	/**
	* 主模板编译器
	*
	* @param string $compiled_template_filename Compiled Template Filename
	* @desc Creates Compiled PHP Template
	*/
	function compile($tpl_file = '', $cpl_file = ''){
		$this->_init($tpl_file);
		$this->_cplDir = dirname($cpl_file) . DS;
		/*** 
		 * 替换模板如果存在子模板则进行替换,子模板格式为:
		 * <!--#include file="module-action.htm" -->
		*/
		$sub = preg_match_all('/<!--#include file="([a-zA-Z0-9?._-]+)" -->/i', $this->_template, $var);
	
	 	$sub = preg_match_all('/<!--#include file="([a-z0-9?\\/._-]+)" -->/i', $this->_template, $var);
	
		 
	
		if (!empty ($sub)) {
			foreach ($var[1] as $subfile) {
				if ($this->_check_subfile($subfile)) {
					if($this->_combinChild===true){
						//debug(file_exists($this->_tplDir . $subfile),$this->_tplDir . $subfile);
						$replace = implode('', file($this->_tplDir . $subfile));//读取子模板内容
					}else{
						$replace = "<?=Emvc::getElement('$subfile')?\>";//
					}
				} else {
					$replace = '<br />Parser Error: Subtemplate not found: [\'' . $subfile . '\']<br />';
				}
				$this->_template = str_replace('<!--#include file="' . $subfile . '" -->', $replace, $this->_template);
			}
		}
		/**
		 * 替换<!--{else}-->
		 * <!--{/loop}-->
		 * <!--{/if}-->
		 */
		$pattern = array (
			'/<!--\{\/if\}-->/',
			'/<!--\{else\}-->/',
			'/<!--\{\/loop\}-->/'
		);
		$rpc = array (
			"<?php\n\t}\n?>",
			"<?php\n\t}else{\n?>",
			"<?php\n\t}\n\t\t}\n?>"
		);
		$this->_template = preg_replace($pattern, $rpc, $this->_template);
		/**
		 * 替换:
		 * <!--{loop $array $key=>$value}-->
		 * <!--{if expresion}-->
		 * <!--{elseif expresion}-->
		 */
		if (preg_match_all("/<!--\{(.+?)\}-->/", $this->_template, $var)) {
			//debug($var,$pattern);
			foreach ($var[1] as $tag) {
				if (preg_match('/^[\s]*(if|elseif|loop)[\s]*/i', $tag, $match)) {
					$pattern = '<!--{' . $tag . '}-->';
					//debug($var,htmlspecialchars($pattern),$tag);
					$arg = substr($tag, strlen($match[0]));
					if ($match[1] == 'loop') { //loop
						$rpc = $this->_parseLoop($arg);
					}elseif($match[1] == 'if' || $match[1] == 'elseif'){
						$rpc=$this->_parseIf($arg,$match[1]);
						//debug(htmlspecialchars($rpc));
					}else{
						$rpc=false;
					}
					//debug(htmlspecialchars($rpc));
					if($rpc){
						$this->_template = str_replace($pattern, $rpc, $this->_template);
						//debug(htmlspecialchars($pattern),htmlspecialchars($rpc),htmlspecialchars($this->_template));
					}
				}
			}
		}
		/**
		 * 替换变量,例如：
		 * $bb='_____________';
		 * $aa='!@@@@@@@$bb@@@@@@@!';
		 * $cc='bb';
		 * $aa=str_replace('$'.$cc,$$cc,$aa);
		 * debug($aa);
		 * 得到显示为：
		 * !@@@@@@@_____________@@@@@@@!
		 */
		//替换变量及语言,变量为{varname.name},语言为{.hello word!.}
		if (preg_match_all('/{(.+?)}/', $this->_template, $var)) {
			
		}
		if (preg_match_all('/{(.+?)}/', $this->_template, $var)) {
			foreach ($var[1] as $tag) {
				if ($tag[0] === '.' && substr($tag, -1, 1) === '.') { //语言
					$replacement = "<?=gettext('" . addslashes(substr($tag, 1, -1)) . "')?>";
				} else { //变量
					$varName = $this->_parseExprssion($tag);
					$replacement = "<?=" . $varName . "?>";
				}
				$this->_template = str_replace('{' . $tag . '}', $replacement, $this->_template);
			}
		}
		//debug($var, '<pre>' . htmlspecialchars($this->_template));
		//更换misc资源
		$tpl_url_root = $this->get('_urlThemeRoot', '/views/defaut/');
		// debug($tpl_url_root);
		$pattern = array (
			'/"(..\/)*misc\//',
			"/'(..\/)*misc\//",
			'/url\((..\/)*misc\//',
			'/=(..\/)*misc\//'
		);
		$rpc= array (
			'"' . $tpl_url_root . 'misc/',
			'\'' . $tpl_url_root . 'misc/',
			'url(' . $tpl_url_root . 'misc/',
			'=' . $tpl_url_root . 'misc/',
			
		);
		$this->_template = preg_replace($pattern, $rpc, $this->_template);
		//	存储编译后的模板
		$hd = $this->save($cpl_file, $this->_template);
		//debug('<pre>' . htmlspecialchars($this->_template));
		if (!$hd) {
			trigger_error('Could not write compiled file:(' . $cpl_file . ')', E_USER_ERROR);
		}
		return true;
	}

	
	
	/**
	 * 解析if(),elseif()语句
	 * <code>
	 * <!--{ if !empty(qihoo_status.bb.cc) && searchbo>=xstatus && aaa(date,time,second)!=4 || (bbb>=6) && bbb<100 && aaa(date)<100 && aaa!=90}-->
	 * 被解析为
	 * <?php
	 * 	if(!empty($qihoo_status['bb']['cc']) && $searchbo>=$xstatus && aaa($date,$time,$second)!=4 || ($bbb>=6) && $bbb<100 && aaa($date)<100 && $aaa!=90)
	 * 	{
	 * ?>
	 * </code>
	 */
	function _parseIf($str='',$if_else='if'){
		if(preg_match_all('/(\$[a-zA-Z_][a-zA-Z0-9._]*)/',trim($str),$var)){
			$str=$this->_parseExprssion($str);//debug($str,$var);
			if($if_else==='if'){
				return "<?php\n\tif(".$str."){\n?>";
			}else{
				return "<?php\n\t}elseif(".$str."){\n?>";
			}
		}else{
			return false;
		}
	}
	function _parseLoop($str = null) {
		static $i=0;
		$str=preg_replace('/(\s)+/',' ',$str);
		$rtn='';
		$counter='$i';
		if($i)$counter.$i;
		if($str){
			if(strpos($str,' ')){
				$arr= explode(' ', trim($str));
				$var=$this->_parseExpressName($arr[0]);
				$cnt=count($arr);
				if($cnt===4){
					$counter=$arr[3];
					$rtn=$var. ' as '.$arr[1].'=>'.$arr[2];
				}elseif($cnt==3){
					$rtn=$var. ' as '.$arr[1].'=>'.$arr[2];
				}elseif($cnt==2){
					$rtn=$var. ' as '.$arr[1];
				}else{
					return false;
				}
			}else{
				$var=$this->_parseExpressName($str);
				$rtn='('.$var.' as $value){';
			}
			$str="<?php\nif(!empty(".$var.") && is_array(".$var.")){\n\t$counter=-1;\n\tforeach(" .$rtn.'){'."\n\t\t$counter++\n?>";
			//debug($rtn,$var);
			$i++;
			return $str;
		}else{
			return false;
		}
	}
	function _parseExprssion($str=''){
		if(preg_match_all('/(\$[a-zA-Z_][a-zA-Z0-9.$_]*)/',trim($str),$var)){
			$rpc=$this->_parseVarMore($var[1]);
			$str=str_replace($var[1],$rpc,$str);
		}
		return $str;
	}
	function _parseVarMore($arr){
		if(is_array($arr) && $arr){
			foreach($arr as $key=>$value){
				$arr[$key]=$this->_parseExpressName($value);
			}
			return $arr;
		}else{
			return false;
		}
	}
	function _parseExpressName($tag) {
		if (strpos($tag, '.')) {
			list ($parent, $tag) = explode('.', $tag, 2);
			$obj = $parent;
			while (is_int(strpos($tag, '.'))) {
				list ($parent, $tag) = explode('.', $tag, 2);
				if(is_numeric($parent)) {
					$obj .= '[' . $parent . ']';
				} else {
					$obj .= '["' . $parent . '"]';
				}
			}
			if (!is_numeric($tag)) {
				$obj .= '["' . $tag . '"]';
			} else {
				$obj .= "[$tag]";
			}
		} else {
			if($tag){
				$obj = $tag;
			}else{
				$obj='';
			}
		}
		return $obj;
	}
	function _regexFuncVars($arr){
		if(is_array($arr) && $arr){
			foreach($arr as $key=>$value){
				$arr[$key]='/'.$value.'(?!\()/';
			}
			return $arr;
		}else{
			return false;
		}
	}
	function _check_subfile($subfile) {
		$pos = strpos($subfile, '.php');
		if ($pos !== false) {
			$file = $this->_tplDir . substr($subfile, 0, $pos +4);
			if (file_exists($file)) {
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}
}
?>